/*******************************************************************************
 * Copyright (c) 2004, 2005 Elias Volanakis and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *聽聽聽聽Elias Volanakis - initial API and implementation
 *******************************************************************************/
package edu.ccut.saturn.studio.logic.parts;

import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.List;

import org.eclipse.draw2d.ConnectionAnchor;
import org.eclipse.draw2d.Figure;
import org.eclipse.draw2d.IFigure;
import org.eclipse.draw2d.Label;
import org.eclipse.draw2d.geometry.Point;
import org.eclipse.draw2d.geometry.Rectangle;
import org.eclipse.gef.ConnectionEditPart;
import org.eclipse.gef.EditPolicy;
import org.eclipse.gef.GraphicalEditPart;
import org.eclipse.gef.NodeEditPart;
import org.eclipse.gef.Request;
import org.eclipse.gef.RequestConstants;
import org.eclipse.gef.commands.Command;
import org.eclipse.gef.editparts.AbstractGraphicalEditPart;
import org.eclipse.gef.editpolicies.GraphicalNodeEditPolicy;
import org.eclipse.gef.requests.CreateConnectionRequest;
import org.eclipse.gef.requests.ReconnectRequest;
import org.eclipse.gef.tools.DirectEditManager;
import org.eclipse.jface.viewers.TextCellEditor;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.Image;

import edu.ccut.saturn.studio.Activator;
import edu.ccut.saturn.studio.Images;
import edu.ccut.saturn.studio.logic.figure.AuthDeptye;
import edu.ccut.saturn.studio.logic.figure.ExitFigure;
import edu.ccut.saturn.studio.logic.figure.PageFigure;
import edu.ccut.saturn.studio.logic.figure.SaturnFigure;
import edu.ccut.saturn.studio.logic.figure.SaturnLayout;
import edu.ccut.saturn.studio.logic.model.BasicShape;
import edu.ccut.saturn.studio.logic.model.Connection;
import edu.ccut.saturn.studio.logic.model.Shape;
import edu.ccut.saturn.studio.logic.model.ShapesDiagram;
import edu.ccut.saturn.studio.logic.model.commands.ConnectionCreateCommand;
import edu.ccut.saturn.studio.logic.model.commands.ConnectionReconnectCommand;
import edu.ccut.saturn.studio.logic.model.commands.FakeCommand;
import edu.ccut.saturn.studio.logic.model.saturn.SaturnActionNode;
import edu.ccut.saturn.studio.logic.model.saturn.SaturnBaseComponentNode;
import edu.ccut.saturn.studio.logic.model.saturn.SaturnLogicNode;
import edu.ccut.saturn.studio.logic.model.saturn.SaturnParameter;
import edu.ccut.saturn.studio.logic.model.saturn.logic.SaturnStartNodeInLogic;
import edu.ccut.saturn.studio.logic.parts.policy.SaturnDirectEditPolicy;
import edu.ccut.saturn.studio.logic.parts.policy.SaturnTipParameterEditPolicy;
import edu.ccut.saturn.studio.util.ConversionUtil;

public class ShapeEditPart extends AbstractGraphicalEditPart implements
		PropertyChangeListener, NodeEditPart {

	private ConnectionAnchor anchor;
	protected DirectEditManager manager;

	public void activate() {
		if (!isActive()) {
			super.activate();
			((BasicShape) getModel()).addPropertyChangeListener(this);
		}
	}

	protected void createEditPolicies() {
		installEditPolicy("tool_tip", new SaturnTipParameterEditPolicy());
		installEditPolicy(EditPolicy.COMPONENT_ROLE,
				new ShapeComponentEditPolicy());

		installEditPolicy(EditPolicy.DIRECT_EDIT_ROLE,
				new SaturnDirectEditPolicy());
		installEditPolicy(EditPolicy.GRAPHICAL_NODE_ROLE,
				new GraphicalNodeEditPolicy() {

					protected Command getConnectionCompleteCommand(
							CreateConnectionRequest request) {

						ConnectionCreateCommand cmd = (ConnectionCreateCommand) request
								.getStartCommand();
						cmd.setTarget((Shape) getHost().getModel());
						return cmd;

					}

					protected Command getConnectionCreateCommand(
							CreateConnectionRequest request) {
						Shape source = (Shape) getHost().getModel();
						int style = ((Integer) request.getNewObjectType())
								.intValue();
						ConnectionCreateCommand cmd = new ConnectionCreateCommand(
								source, style);
						request.setStartCommand(cmd);
						return cmd;

					}

					protected Command getReconnectSourceCommand(
							ReconnectRequest request) {
						Connection conn = (Connection) request
								.getConnectionEditPart().getModel();
						Shape newSource = (Shape) getHost().getModel();
						ConnectionReconnectCommand cmd = new ConnectionReconnectCommand(
								conn);
						cmd.setNewSource(newSource);
						return cmd;
					}

					protected Command getReconnectTargetCommand(
							ReconnectRequest request) {
						Connection conn = (Connection) request
								.getConnectionEditPart().getModel();
						Shape newTarget = (Shape) getHost().getModel();
						ConnectionReconnectCommand cmd = new ConnectionReconnectCommand(
								conn);
						cmd.setNewTarget(newTarget);
						return cmd;
					}
				});
	}

	@SuppressWarnings("static-access")
	@Override
	public void performRequest(Request req) {

		if (req.getType() == RequestConstants.REQ_DIRECT_EDIT) {
			if (manager == null) {
				Figure figure = (Figure) getFigure();
				manager = new NodeDirectEditManager(this, TextCellEditor.class,
						new NodeCellEditorLocator(figure));
			}
			manager.show(); // show the Editor
		}
		if (req.getType() == RequestConstants.REQ_OPEN
				&& (((Shape) getModel()).isIschanged() == false)) {

//			getViewer().getEditDomain().getCommandStack().execute(
//					new OpenDialogCommand(((Shape) getModel()).getDialog(),
//							(Shape) getModel()));
			((Shape) getModel()).getDialog().open();
//			if(((ParentPrimaryDialog)((Shape) getModel()).getDialog()).getIsOK()){
//				getViewer().getEditDomain().getCommandStack().execute(new FakeCommand());
//			}
		
		}
	}

	protected IFigure createFigure() {
		Object model = getCastedModel();
		if (model instanceof Shape) {
			Shape shape = (Shape) model;
			return shape.getFigure();
		}

		return null;
	}

	public void deactivate() {
		if (isActive()) {
			super.deactivate();
			((BasicShape) getModel()).removePropertyChangeListener(this);
		}
	}

	private Shape getCastedModel() {
		return (Shape) getModel();
	}

	protected ConnectionAnchor getConnectionAnchor() {
		if (anchor == null) {
			if (getModel() instanceof Shape) {
				anchor = new BorderAnchor(getFigure());
			} else {
				// if Shapes gets extended the conditions above must be updated
				throw new IllegalArgumentException("unexpected model");
			}
		}
		return anchor;
	}

	protected List<Connection> getModelSourceConnections() {
		return getCastedModel().getSourceConnections();
	}

	protected List<Connection> getModelTargetConnections() {
		return getCastedModel().getTargetConnections();
	}

	public ConnectionAnchor getSourceConnectionAnchor(
			ConnectionEditPart connection) {
		return getConnectionAnchor();
	}

	public ConnectionAnchor getSourceConnectionAnchor(Request request) {
		return getConnectionAnchor();
	}

	public ConnectionAnchor getTargetConnectionAnchor(
			ConnectionEditPart connection) {
		return getConnectionAnchor();
	}

	public ConnectionAnchor getTargetConnectionAnchor(Request request) {
		return getConnectionAnchor();
	}

	public void propertyChange(PropertyChangeEvent evt) {
		getViewer().getEditDomain().getCommandStack().execute(new FakeCommand());
		String prop = evt.getPropertyName();
		((ShapesDiagram) (((Shape) getModel()).getParent()))
				.modifyShape((Shape) getModel());
		if (Shape.SIZE_PROP.equals(prop) || Shape.LOCATION_PROP.equals(prop)
				|| Shape.NAME_PROP.equals(prop)
				|| Shape.PROPERTY_PARAMETERS.equals(prop)
				|| Shape.PROPERTERY_CHANGS.equals(prop)) {
			refreshVisuals();

		} else if (Shape.SOURCE_CONNECTIONS_PROP.equals(prop)) {
			refreshSourceConnections();
		} else if (Shape.TARGET_CONNECTIONS_PROP.equals(prop)) {
			refreshTargetConnections();
		}
	}

	protected void refreshVisuals() {
		// Rectangle bounds = new Rectangle(getCastedModel().getLocation(),
		// getCastedModel().getSize());
		Rectangle bounds = new Rectangle(getCastedModel().getLocation().x,
				getCastedModel().getLocation().y, -1, -1);

		IFigure figure = super.getFigure();
		((GraphicalEditPart) getParent()).setLayoutConstraint(this, figure,
				bounds);
		Shape model = getCastedModel();
		if (figure instanceof PageFigure) {
			changeView(figure, model);
		}
		if (figure instanceof SaturnFigure) {
			if (model instanceof Shape) {
				Shape shape = (Shape) model;
				SaturnFigure saturnFigure = (SaturnFigure) figure;
				saturnFigure.setName(shape.getName());
			}
		}

	}

	private void changeView(IFigure figure, Shape model) {
		PageFigure pagefigure = (PageFigure) figure;
		pagefigure.getImageFigure().removeAll();
		pagefigure.getLetterFigure().removeAll();
		if (model.isIschanged() == true) {
			// Label namelabel = new Label(model.getName(),
			// imagefactory(model));
			//
			// Font nameFont = new Font(null, "Arial", 10, SWT.BOLD);
			// Font parameterFont = new Font(null, "瀹嬩綋", 8, SWT.BOLD);
			// namelabel.setFont(nameFont);
			// pagefigure.getImageFigure().add(namelabel);
			reputLabel(model.getName(), 10, pagefigure.getImageFigure(),
					imagefactory(model));
			// ***********************************************
			// stringlayout(model.getName(), pagefigure.getImageFigure(),
			// imagefactory(model), 4, 7);
			// ***********************************************
			// Label att1 = new Label("杈撳叆绫诲瀷");
			// att1.setFont(parameterFont);
			// Label att2 = new Label("杈撳嚭绫诲瀷");
			// att2.setFont(parameterFont);
			// Label att1 = new Label(ISaturnIcons.BLUE_IN);
			// Label att2 = new Label(ISaturnIcons.BLUE_OUT);
			// Label att3 = new Label(ISaturnIcons.BLUE_INOUT);
			// pagefigure.getLetterFigure().add(att1);
			createparameterfigure(model, pagefigure, "in", "杈撳叆");
			// pagefigure.getLetterFigure().add(att2);
			createparameterfigure(model, pagefigure, "out", "杈撳嚭");
			// pagefigure.getLetterFigure().add(att3);
			createparameterfigure(model, pagefigure, "in-out", "杈撳叆杈撳嚭");
			// Color backgroundColor = new Color(null, 255, 255, 206);
			// pagefigure.setBackgroundColor(backgroundColor);
			pagefigure.setOpaque(true);
			pagefigure.setBorder(new ExitFigure());
		} else {
			Label namelabel = new Label(fstringlayout(model));
			Label imageLabel = new Label(imageFactory(model));

			pagefigure.getImageFigure().add(imageLabel);
			pagefigure.getImageFigure().setLocation(
					new Point(pagefigure.getLocation().x + 5, pagefigure
							.getLocation().y));

			pagefigure.getLetterFigure().add(namelabel);

			pagefigure.setBorder(null);
		}

	}

	private Image imageFactory(Shape model) {
		if (model instanceof SaturnLogicNode) {
//			return ISaturnIcons.LOGIC_ICON;
			return Activator.getImage(Images.LOGIC_ICON);
		} else if (model instanceof SaturnBaseComponentNode) {
//			return ISaturnIcons.COMPONENT_ICON;
			return Activator.getImage(Images.COMPONENT_ICON);
		} else if (model instanceof SaturnActionNode) {
			return Activator.getImage(Images.ACTION_ICON);
		} else if (model instanceof SaturnStartNodeInLogic) {
			return Activator.getImage(Images.START_ICON);
		}
		else
			return null;
	}

	private Image imagefactory(Shape model) {
		if (model instanceof SaturnLogicNode) {
//			return ISaturnIcons.LOGIC_ICON_SMALL;
			return Activator.getImage(Images.LOGIC_ICON_SMALL);
		} else if (model instanceof SaturnBaseComponentNode) {
//			return ISaturnIcons.COMPONENT_ICON_SMALL;
			return Activator.getImage(Images.COMPONENT_ICON_SMALL);
		} else if (model instanceof SaturnActionNode) {
			return Activator.getImage(Images.ACTION_ICON_SMALL);
		} else if (model instanceof SaturnStartNodeInLogic) {
			return Activator.getImage(Images.START_ICON_SMALL);
		}
		else
			return null;
	}

	private void createparameterfigure(Object model, PageFigure pagefigure,
			String flag, String flats) {
		int i = 0;
		for (SaturnParameter saturnParameter : ((Shape) model).getParameters()) {

			if (saturnParameter.getPassingType().equals(flag)
					|| saturnParameter.getPassingType().equals(flats)) {
				Font fparameterFont = new Font(null, "瀹嬩綋", 8, SWT.NULL);

				reputLabel(saturnParameter, 12, pagefigure.getLetterFigure(),
						imagefactory2(saturnParameter.getPassingType()));
				i++;
			}

		}
		// TODO:濡傛灉姝ゅ弬鏁扮被鍨嬬殑鍙傛暟涓�0锛屾斁涓�涓┖鐨刲abel
		// if (i==0) {
		// pagefigure.getLetterFigure().add(new Label(imagefactory2(flag)));
		// }
	}

	private String fstringlayout(Shape model) {
		if (AuthDeptye.isValid(model.getName())) {
			return SaturnLayout.restrictNameLong(model.getName(), 8);
		} else {
			return SaturnLayout.restrictNameLong(model.getName(), 4);
		}

	}

	public void reputLabel(Object object, int len, IFigure figure, Image image) {
		if (object instanceof SaturnParameter) {
			delaminationInFigure(((SaturnParameter) object).getName(), len, figure, image,
					((SaturnParameter) object).getValueKey());
		} else if (object instanceof String) {
			delaminationInFigure((String) object, len, figure, image, (String) object);
		}

	}

	private void delaminationInFigure(String name, int len, IFigure figure, Image image,
			String tooltip) {
		if (name.length() > len) {
			String s = name.substring(0, len);
			Label label = new Label(s, image);
			label.setToolTip(new Label(tooltip));
			figure.add(label);
			name = name.substring(len, name.length());
			Label label2 = new Label(SaturnLayout.restrictNameLong(name, 15));
			label2.setToolTip(new Label(tooltip));
			figure.add(label2);
		} else {
			Label label = new Label(name, image);
			label.setToolTip(new Label(tooltip));
			figure.add(label);
		}

	}

	private Image imagefactory2(String s) {
		if (s.equals("in") || s.equals("杈撳叆")) {
//			return ISaturnIcons.BLUE_IN;
			return Activator.getImage(Images.BLUE_IN);
		} else if (s.equals("out") || s.equals("杈撳嚭")) {
//			return ISaturnIcons.BLUE_OUT;
			return Activator.getImage(Images.BLUE_OUT);
		} else if (s.equals("in-out") || s.equals("杈撳叆杈撳嚭")) {
//			return ISaturnIcons.BLUE_INOUT;
			return Activator.getImage(Images.BLUE_INOUT);
		} else
			return null;

	}

	public boolean isShowTipOnTop() {
		return true;
	}

	public String getToolTipContent() {
		Shape s = ((Shape) getModel());
		List<SaturnParameter> list = ConversionUtil.scopeMapFromXmlToSurface(s
				.getParameters());
		String ss = s.getName();// "parameters";
		for (int i = 0; i < list.size(); i++) {
			ss += "\n" + "[" + list.get(i).getName() + "]" + "["
					+ list.get(i).getPassingType() + "]" + "\r\t\n";

		}
		return ss;
	}
}